3.8 Position adjustments

3.8.1 Exercises

  1. What is the problem with this plot? How could you improve it?

There is overplotting. To fix this I would use a jitter position adjustment to decrease overplotting.

ggplot(data = mpg, mapping = aes(x = cty, y = hwy)) +
  geom_point(position = "jitter")

  1. What parameters to geom_jitter() control the amount of jittering?

Width controls the amount of vertical displacement. Height controls the amount of horizontal displacement.

  1. Compare and contrast geom_jitter() with geom_count()

The geom geom_jitter() adds random variation to the locations points of the graph. The geom geom_count() sizes the points relative to the number of observations.

  1. What’s the default position adjustment for geom_boxplot()? Create a visualisation of the mpg dataset that demonstrates it?

The default position for geom_boxplot() is “dodge2”.

ggplot(data = mpg, aes(x = drv, y = hwy, colour = class)) +
  geom_boxplot()  

ggplot(data = mpg, aes(x = drv, y = hwy, colour = class)) +
  geom_boxplot(position = "identity")

3.9 Coordinate systems

  • coord_flip() switches the x and y axes. This is useful to make horizontal boxplots.

    • ggplot(data = mpg, mapping = aes(x = class, y = hwy)) + geom_boxplot() ggplot(data = mpg, mapping = aes(x = class, y = hwy)) + geom_boxplot() + coord_flip()
  • coord_quickmap() sets the aspect ratio correctly for maps.

    • nz <- map_data(“nz”) ggplot(nz, aes(long, lat, group = group)) + geom_polygon(fill = “white”, colour = “black”) ggplot(nz, aes(long, lat, group = group)) + geom_polygon(fill = “white”, colour = “black”) + coord_quickmap()
  • coord_polar() uses polar coordinates. Polar coordinates reveal an interesting connection between a bar chart and a Coxcomb chart.

    • bar <- ggplot(data = diamonds) + geom_bar( mapping = aes(x = cut, fill = cut), show.legend = FALSE, width = 1 ) + theme(aspect.ratio = 1) + labs(x = NULL, y = NULL) bar + coord_flip() bar + coord_polar()

3.9.1 Exercises

  1. Turn a stacked bar chart into a pie chart using coord_polar().
ggplot(mpg, aes(x = factor(1), fill = drv)) +
  geom_bar(width = 1) +
  coord_polar(theta = "y")

  1. What does labs() do? Read the documentation.

It adds axis titles, plot titles, and a caption to the plot.

  1. What’s the difference between coord_quickmap() and coord_map()?

coord_map() makes a three-dimensional Earth onto a two-dimensional plane. The coord_quickmap() ignores the curvature of Earth and adjusts the map for the latitude/longitude ratio. The coord_quickmap() project is faster than coord_map().

  1. What does the plot below tell you about the relationship between city and highway mpg? Why is coord_fixed() important? What does geom_abline() do?
ggplot(data = mpg, mapping = aes(x = cty, y = hwy)) +
  geom_point() + 
  geom_abline() +
  coord_fixed()

What does the plot below tell you about the relationship between city and highway mpg? Why is coord_fixed() important? What does geom_abline() do?

The plot tells me the line geom_abline() is going to make is going to be a 45-degree angle. The angle makes it easy to compare the highway and city mileage to the case in which city and highway MPG were equal geom_coord() makes the line be a 45-degree angle.

3.10 The layered grammar of graphics

  • Add position adjustments, stats, coordinate systems, and faceting

    • ggplot(data = ) + ( mapping = aes(), stat = , position = ) + +

    • seven parameters in the template compose the grammar of graphics, a formal system for building plots.
    • could choose a geometric object to represent each observation in the transformed data.
    • select a coordinate system to place the geoms into. You’d use the location of the objects which is itself an aesthetic property to display the values of the x and y variables.
    • could use this method to build any plot that you imagine

5.1 Prerequisites

-library(nycflights13) library(tidyverse)

-If you want to use the base version of these functions after loading dplyr, you’ll need to use their full names: stats::filter() and stats::lag().
  • To see the whole dataset, you can run View(flights

  • int stands for integers.

  • dbl stands for doubles, or real numbers.

  • chr stands for character vectors, or strings.

  • dttm stands for date-times (a date + a time)

  • lgl stands for logical, vectors that contain only TRUE or FALSE.

  • fctr stands for factors, which R uses to represent categorical variables with fixed possible values.

  • date stands for dates.

  • Five key dplyr functions

    • Pick observations by their values (filter()).
    • Reorder the rows (arrange()).
    • Pick variables by their names (select()).
    • Create new variables with functions of existing variables (mutate()).
    • Collapse many values down to a single summary (summarise()).

5.2 Filter rows with filter()

  • Filter() allows you to subset observations based on their values

    • first argument is the name of the data frame. The second and subsequent arguments are the expressions that filter the data frame.
  • To save the result need to use the assignment operator, <-:

    • jan1 <- filter(flights, month == 1, day == 1)
    • use == not =
    • & is “and”, | is “or”, and ! is “not”
    • short-hand m is x %in% y. Select every row where x is one of the values in y.
  • If you want to determine if a value is missing, use is.na()
  • filter() only includes rows where the condition is TRUE; it excludes both FALSE and NA values.

5.2.4 Exercises

  1. 1a. All flights that had an arrival delay of two or more hours
filter(flights, arr_delay >= 120)

1b. All flights that had flew to Houston (IAH or HOU)

filter(flights, dest == "IAH" | dest == "HOU")

1c. All flights that had were operated by United, American, or Delta

filter(flights, carrier %in% c("AA", "DL", "UA"))

1d. All flights that had departed in summer (July, August, and September

filter(flights, month == 7 | month == 8 | month == 9)

1e. All flights that had arrived more than two hours late, but didn’t leave late

filter(flights, arr_delay > 120, dep_delay <= 0)

1f. All flights that were delayed by at least an hour, but made up over 30 minutes in flight

filter(flights, dep_delay >= 60, dep_delay - arr_delay > 30)

1g. All flights that were dparted between midnight and 6am (inclusive)

filter(flights, dep_time %% 2400 <= 600)
  1. Another useful dplyr filtering helper is between(). What does it do? Can you use it to simplify the code needed to answer the previous challenges?

The expression between(x, left, right) is equivalent to x >= left & x <= right. I could had use it to simplify the code needed to answer the previous challenges

  1. How many flights have a missing dep_time? What other variables are missing? What might these rows represent?
filter(flights, is.na(dep_time))

1000 flights have a missing dep_time. The arrival time (arr_time) is also missing.

  1. Why is NA ^ 0 not missing? Why is NA | TRUE not missing? Why is FALSE & NA not missing? Can you figure out the general rule? (NA * 0 is a tricky counterexample!)

NA ^ 0 is not missing because for all numeric values x ^ 0 = 1 NA | TRUE not missing because x or TRUE is TRUE for all values of x FALSE & NA not missing becaues anything and FALSE is always FALSE NA times 0 is not equal to 0 is that × times ∞ and x times −∞ is undefined. R represents undefined results as NaN (not a number).

5.3 Arrange rows with arrange()

  • arrange() works similarly to filter()
    • except that instead of selecting rows it changes their order
    • It takes a data frame and a set of column names (or more complicated expressions) to order by.
  • Use desc() to re-order by a column in descending order:
    • arrange(flights, desc(dep_delay))
  • Missing values are always sorted at the end.

5.3.1 Exercises

  1. How could you use arrange() to sort all missing values to the start? (Hint: use is.na()).
arrange(flights, desc(is.na(dep_time)), dep_time)
  1. Sort flights to find the most delayed flights. Find the flights that left earliest.
arrange(flights, dep_delay)

Flight B6 97 (JFK to DEN) depart on December 07, 2013 at 21:23 departed 43 minutes early.

  1. Sort flights to find the fastest (highest speed) flights.
fastest_flights <- mutate(flights, mph = distance / air_time * 60)
fastest_flights <- select(
  fastest_flights, mph, distance, air_time,
  flight, origin, dest, year, month, day
)
  1. Which flights travelled the farthest? Which travelled the shortest?
arrange(flights, desc(distance))

The longest flight is HA 51, JFK to HNL, which is 4,983 miles.

arrange(flights, distance)

The shortest flight is US 1632, EWR to LGA, which is only 17 miles.

5.4 Select columns with select()

  • select() allows you to rapidly zoom in on a useful subset using operations based on the names of the variables.

  • starts_with(“abc”): matches names that begin with “abc”.

  • ends_with(“xyz”): matches names that end with “xyz”.

  • contains(“ijk”): matches names that contain “ijk”.

  • matches(“(.)\1”): selects variables that match a regular expression. This one matches any variables that contain repeated characters. You’ll learn more about regular expressions in strings.

  • num_range(“x”, 1:3): matches x1, x2 and x3.

  • ?select for more details

  • use rename(), which is a variant of select() that keeps all the variables that aren’t explicitly mentioned:

    • rename(flights, tail_num = tailnum)

5.4.1 Exercises

  1. Brainstorm as many ways as possible to select dep_time, dep_delay, arr_time, and arr_delay from flights.
select(flights, dep_time, dep_delay, arr_time, arr_delay)
select(flights, 4, 6, 7, 9)
  1. What happens if you include the name of a variable multiple times in a select() call?

The select() call ignores the duplication.

  1. What does the one_of() function do? Why might it be helpful in conjunction with this vector?
vars <- c("year", "month", "day", "dep_delay", "arr_delay")

The one_of() function selects variables with a character vector rather than unquoted variable name arguments. This is helpful because it is easier to make a character vectors with variable names than to create unquoted variable names.

  1. Does the result of running the following code surprise you? How do the select helpers deal with case by default? How can you change that default?
select(flights, contains("TIME"))

The default behavior for contains() is to ignore case. Can change the behavior by adding the argument ignore.case = FALSE.

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKQXV0aG9yOiBOYXRlIFdhbHRvbgotLS0KCgojIyMgMy44IFBvc2l0aW9uIGFkanVzdG1lbnRzCgotIENvbG9yIGEgYmFyIGNoYXJ0IHVzaW5nIGVpdGhlciB0aGUgY29sb3VyIGFlc3RoZXRpYywgb3IgZmlsbDogIAoKICAtIGdncGxvdChkYXRhID0gZGlhbW9uZHMpICsgCiAgZ2VvbV9iYXIobWFwcGluZyA9IGFlcyh4ID0gY3V0LCBjb2xvdXIgPSBjdXQpKQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzKSArIAogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IGN1dCwgZmlsbCA9IGN1dCkpCgotIEJhcnMgYXJlIGF1dG9tYXRpY2FsbHkgc3RhY2tlZCAgCiAgLSBnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzKSArIAogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IGN1dCwgZmlsbCA9IGNsYXJpdHkpKQoKLSBQb2ludHMgb24gYSBncmlkIGFuZCBvdGhlciBwb2ludHMgb3ZlcmxhcCBlYWNoIG90aGVyICAKICAtIG92ZXJwbG90dGluZyAgCgotIFNwcmVhZHMgdGhlIHBvaW50cyAKCiAgICAtIGdncGxvdChkYXRhID0gbXBnKSArIAogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3kpLCBwb3NpdGlvbiA9ICJqaXR0ZXIiKQoKCgojIyAzLjguMSBFeGVyY2lzZXMKCjEuIFdoYXQgaXMgdGhlIHByb2JsZW0gd2l0aCB0aGlzIHBsb3Q/IEhvdyBjb3VsZCB5b3UgaW1wcm92ZSBpdD8KCmBgYHtyIGVjaG8gPSBGQUxTRX0KZ2dwbG90KGRhdGEgPSBtcGcsIG1hcHBpbmcgPSBhZXMoeCA9IGN0eSwgeSA9IGh3eSkpICsgCiAgZ2VvbV9wb2ludCgpCmBgYAoKClRoZXJlIGlzIG92ZXJwbG90dGluZy4gVG8gZml4IHRoaXMgSSB3b3VsZCB1c2UgYSBqaXR0ZXIgcG9zaXRpb24gYWRqdXN0bWVudCB0byBkZWNyZWFzZSBvdmVycGxvdHRpbmcuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBtcGcsIG1hcHBpbmcgPSBhZXMoeCA9IGN0eSwgeSA9IGh3eSkpICsKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gImppdHRlciIpCmBgYAoKCjIuIFdoYXQgcGFyYW1ldGVycyB0byBnZW9tX2ppdHRlcigpIGNvbnRyb2wgdGhlIGFtb3VudCBvZiBqaXR0ZXJpbmc/CgpXaWR0aCBjb250cm9scyB0aGUgYW1vdW50IG9mIHZlcnRpY2FsIGRpc3BsYWNlbWVudC4KSGVpZ2h0IGNvbnRyb2xzIHRoZSBhbW91bnQgb2YgaG9yaXpvbnRhbCBkaXNwbGFjZW1lbnQuCgoKCjMuIENvbXBhcmUgYW5kIGNvbnRyYXN0IGdlb21faml0dGVyKCkgd2l0aCBnZW9tX2NvdW50KCkKClRoZSBnZW9tIGdlb21faml0dGVyKCkgYWRkcyByYW5kb20gdmFyaWF0aW9uIHRvIHRoZSBsb2NhdGlvbnMgcG9pbnRzIG9mIHRoZSBncmFwaC4gVGhlIGdlb20gZ2VvbV9jb3VudCgpIHNpemVzIHRoZSBwb2ludHMgcmVsYXRpdmUgdG8gdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMuIAoKCjQuIFdoYXTigJlzIHRoZSBkZWZhdWx0IHBvc2l0aW9uIGFkanVzdG1lbnQgZm9yIGdlb21fYm94cGxvdCgpPyBDcmVhdGUgYSB2aXN1YWxpc2F0aW9uIG9mIHRoZSBtcGcgZGF0YXNldCB0aGF0IGRlbW9uc3RyYXRlcyBpdD8KCgpUaGUgZGVmYXVsdCBwb3NpdGlvbiBmb3IgZ2VvbV9ib3hwbG90KCkgaXMgImRvZGdlMiIuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBtcGcsIGFlcyh4ID0gZHJ2LCB5ID0gaHd5LCBjb2xvdXIgPSBjbGFzcykpICsKICBnZW9tX2JveHBsb3QoKSAgCmdncGxvdChkYXRhID0gbXBnLCBhZXMoeCA9IGRydiwgeSA9IGh3eSwgY29sb3VyID0gY2xhc3MpKSArCiAgZ2VvbV9ib3hwbG90KHBvc2l0aW9uID0gImlkZW50aXR5IikKYGBgCgoKCiMjIyAzLjkgQ29vcmRpbmF0ZSBzeXN0ZW1zCgotIGNvb3JkX2ZsaXAoKSBzd2l0Y2hlcyB0aGUgeCBhbmQgeSBheGVzLiBUaGlzIGlzIHVzZWZ1bCB0byBtYWtlIGhvcml6b250YWwgYm94cGxvdHMuIAoKICAgIC0gZ2dwbG90KGRhdGEgPSBtcGcsIG1hcHBpbmcgPSBhZXMoeCA9IGNsYXNzLCB5ID0gaHd5KSkgKyAKICBnZW9tX2JveHBsb3QoKQpnZ3Bsb3QoZGF0YSA9IG1wZywgbWFwcGluZyA9IGFlcyh4ID0gY2xhc3MsIHkgPSBod3kpKSArIAogIGdlb21fYm94cGxvdCgpICsKICBjb29yZF9mbGlwKCkKCi0gY29vcmRfcXVpY2ttYXAoKSBzZXRzIHRoZSBhc3BlY3QgcmF0aW8gY29ycmVjdGx5IGZvciBtYXBzLgoKICAgIC0gbnogPC0gbWFwX2RhdGEoIm56IikKZ2dwbG90KG56LCBhZXMobG9uZywgbGF0LCBncm91cCA9IGdyb3VwKSkgKwogIGdlb21fcG9seWdvbihmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikKZ2dwbG90KG56LCBhZXMobG9uZywgbGF0LCBncm91cCA9IGdyb3VwKSkgKwogIGdlb21fcG9seWdvbihmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikgKwogIGNvb3JkX3F1aWNrbWFwKCkKCi0gY29vcmRfcG9sYXIoKSB1c2VzIHBvbGFyIGNvb3JkaW5hdGVzLiBQb2xhciBjb29yZGluYXRlcyByZXZlYWwgYW4gaW50ZXJlc3RpbmcgY29ubmVjdGlvbiBiZXR3ZWVuIGEgYmFyIGNoYXJ0IGFuZCBhIENveGNvbWIgY2hhcnQuCgogICAgLSBiYXIgPC0gZ2dwbG90KGRhdGEgPSBkaWFtb25kcykgKyAKICBnZW9tX2JhcigKICAgIG1hcHBpbmcgPSBhZXMoeCA9IGN1dCwgZmlsbCA9IGN1dCksIAogICAgc2hvdy5sZWdlbmQgPSBGQUxTRSwKICAgIHdpZHRoID0gMQogICkgKyAKICB0aGVtZShhc3BlY3QucmF0aW8gPSAxKSArCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwpCiAgYmFyICsgY29vcmRfZmxpcCgpCiAgYmFyICsgY29vcmRfcG9sYXIoKQoKCiMjIDMuOS4xIEV4ZXJjaXNlcwoKMS4gVHVybiBhIHN0YWNrZWQgYmFyIGNoYXJ0IGludG8gYSBwaWUgY2hhcnQgdXNpbmcgY29vcmRfcG9sYXIoKS4KCgpgYGB7cn0KZ2dwbG90KG1wZywgYWVzKHggPSBmYWN0b3IoMSksIGZpbGwgPSBkcnYpKSArCiAgZ2VvbV9iYXIod2lkdGggPSAxKSArCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpCmBgYAoKCjIuIFdoYXQgZG9lcyBsYWJzKCkgZG8/IFJlYWQgdGhlIGRvY3VtZW50YXRpb24uCgpJdCBhZGRzIGF4aXMgdGl0bGVzLCBwbG90IHRpdGxlcywgYW5kIGEgY2FwdGlvbiB0byB0aGUgcGxvdC4KCgoKMy4gV2hhdOKAmXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBjb29yZF9xdWlja21hcCgpIGFuZCBjb29yZF9tYXAoKT8KCgpjb29yZF9tYXAoKSBtYWtlcyBhIHRocmVlLWRpbWVuc2lvbmFsIEVhcnRoIG9udG8gYSB0d28tZGltZW5zaW9uYWwgcGxhbmUuIFRoZSBjb29yZF9xdWlja21hcCgpIGlnbm9yZXMgdGhlIGN1cnZhdHVyZSBvZiBFYXJ0aCBhbmQgYWRqdXN0cyB0aGUgbWFwIGZvciB0aGUgbGF0aXR1ZGUvbG9uZ2l0dWRlIHJhdGlvLiBUaGUgY29vcmRfcXVpY2ttYXAoKSBwcm9qZWN0IGlzIGZhc3RlciB0aGFuIGNvb3JkX21hcCgpLgoKCgo0LiBXaGF0IGRvZXMgdGhlIHBsb3QgYmVsb3cgdGVsbCB5b3UgYWJvdXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGNpdHkgYW5kIGhpZ2h3YXkgbXBnPyBXaHkgaXMgY29vcmRfZml4ZWQoKSBpbXBvcnRhbnQ/IFdoYXQgZG9lcyBnZW9tX2FibGluZSgpIGRvPwoKYGBge3J9CmdncGxvdChkYXRhID0gbXBnLCBtYXBwaW5nID0gYWVzKHggPSBjdHksIHkgPSBod3kpKSArCiAgZ2VvbV9wb2ludCgpICsgCiAgZ2VvbV9hYmxpbmUoKSArCiAgY29vcmRfZml4ZWQoKQpgYGAKCldoYXQgZG9lcyB0aGUgcGxvdCBiZWxvdyB0ZWxsIHlvdSBhYm91dCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gY2l0eSBhbmQgaGlnaHdheSBtcGc/IFdoeSBpcyBjb29yZF9maXhlZCgpIGltcG9ydGFudD8gV2hhdCBkb2VzIGdlb21fYWJsaW5lKCkgZG8/CgoKVGhlIHBsb3QgdGVsbHMgbWUgdGhlIGxpbmUgZ2VvbV9hYmxpbmUoKSBpcyBnb2luZyB0byBtYWtlIGlzIGdvaW5nIHRvIGJlIGEgNDUtZGVncmVlIGFuZ2xlLiBUaGUgYW5nbGUgbWFrZXMgaXQgZWFzeSB0byBjb21wYXJlIHRoZSBoaWdod2F5IGFuZCBjaXR5IG1pbGVhZ2UgdG8gdGhlIGNhc2UgaW4gd2hpY2ggY2l0eSBhbmQgaGlnaHdheSBNUEcgd2VyZSBlcXVhbCBnZW9tX2Nvb3JkKCkgbWFrZXMgdGhlIGxpbmUgYmUgYSA0NS1kZWdyZWUgYW5nbGUuCgoKIyMjIDMuMTAgVGhlIGxheWVyZWQgZ3JhbW1hciBvZiBncmFwaGljcwoKLSBBZGQgcG9zaXRpb24gYWRqdXN0bWVudHMsIHN0YXRzLCBjb29yZGluYXRlIHN5c3RlbXMsIGFuZCBmYWNldGluZwoKICAgIC0gZ2dwbG90KGRhdGEgPSA8REFUQT4pICsgCiAgPEdFT01fRlVOQ1RJT04+KAogICAgIG1hcHBpbmcgPSBhZXMoPE1BUFBJTkdTPiksCiAgICAgc3RhdCA9IDxTVEFUPiwgCiAgICAgcG9zaXRpb24gPSA8UE9TSVRJT04+CiAgKSArCiAgPENPT1JESU5BVEVfRlVOQ1RJT04+ICsKICA8RkFDRVRfRlVOQ1RJT04+CiAgCiAgICAtICBzZXZlbiBwYXJhbWV0ZXJzIGluIHRoZSB0ZW1wbGF0ZSBjb21wb3NlIHRoZSBncmFtbWFyIG9mIGdyYXBoaWNzLCBhIGZvcm1hbCBzeXN0ZW0gZm9yIGJ1aWxkaW5nIHBsb3RzLiAKICAgIC0gY291bGQgY2hvb3NlIGEgZ2VvbWV0cmljIG9iamVjdCB0byByZXByZXNlbnQgZWFjaCBvYnNlcnZhdGlvbiBpbiB0aGUgdHJhbnNmb3JtZWQgZGF0YS4KICAgIC0gc2VsZWN0IGEgY29vcmRpbmF0ZSBzeXN0ZW0gdG8gcGxhY2UgdGhlIGdlb21zIGludG8uIFlvdeKAmWQgdXNlIHRoZSBsb2NhdGlvbiBvZiB0aGUgb2JqZWN0cyB3aGljaCBpcyBpdHNlbGYgYW4gYWVzdGhldGljIHByb3BlcnR5IHRvIGRpc3BsYXkgdGhlIHZhbHVlcyBvZiB0aGUgeCBhbmQgeSB2YXJpYWJsZXMuCiAgICAtIGNvdWxkIHVzZSB0aGlzIG1ldGhvZCB0byBidWlsZCBhbnkgcGxvdCB0aGF0IHlvdSBpbWFnaW5lCiAgICAKICAgIAogICAgCiAgICAKIyMjIDUuMSBQcmVyZXF1aXNpdGVzCgotbGlicmFyeShueWNmbGlnaHRzMTMpCmxpYnJhcnkodGlkeXZlcnNlKQoKICAgIC1JZiB5b3Ugd2FudCB0byB1c2UgdGhlIGJhc2UgdmVyc2lvbiBvZiB0aGVzZSBmdW5jdGlvbnMgYWZ0ZXIgbG9hZGluZyBkcGx5ciwgeW914oCZbGwgbmVlZCB0byB1c2UgdGhlaXIgZnVsbCBuYW1lczogc3RhdHM6OmZpbHRlcigpIGFuZCBzdGF0czo6bGFnKCkuCgotIFRvIHNlZSB0aGUgd2hvbGUgZGF0YXNldCwgeW91IGNhbiBydW4gVmlldyhmbGlnaHRzCgotIGludCBzdGFuZHMgZm9yIGludGVnZXJzLgoKLSBkYmwgc3RhbmRzIGZvciBkb3VibGVzLCBvciByZWFsIG51bWJlcnMuCgotIGNociBzdGFuZHMgZm9yIGNoYXJhY3RlciB2ZWN0b3JzLCBvciBzdHJpbmdzLgoKLSBkdHRtIHN0YW5kcyBmb3IgZGF0ZS10aW1lcyAoYSBkYXRlICsgYSB0aW1lKQoKLSBsZ2wgc3RhbmRzIGZvciBsb2dpY2FsLCB2ZWN0b3JzIHRoYXQgY29udGFpbiBvbmx5IFRSVUUgb3IgRkFMU0UuCgotIGZjdHIgc3RhbmRzIGZvciBmYWN0b3JzLCB3aGljaCBSIHVzZXMgdG8gcmVwcmVzZW50IGNhdGVnb3JpY2FsIHZhcmlhYmxlcyB3aXRoIGZpeGVkIHBvc3NpYmxlIHZhbHVlcy4KCi0gZGF0ZSBzdGFuZHMgZm9yIGRhdGVzLgoKCi0gRml2ZSBrZXkgZHBseXIgZnVuY3Rpb25zIAoKICAgIC0gUGljayBvYnNlcnZhdGlvbnMgYnkgdGhlaXIgdmFsdWVzIChmaWx0ZXIoKSkuCiAgICAtIFJlb3JkZXIgdGhlIHJvd3MgKGFycmFuZ2UoKSkuCiAgICAtIFBpY2sgdmFyaWFibGVzIGJ5IHRoZWlyIG5hbWVzIChzZWxlY3QoKSkuCiAgICAtIENyZWF0ZSBuZXcgdmFyaWFibGVzIHdpdGggZnVuY3Rpb25zIG9mIGV4aXN0aW5nIHZhcmlhYmxlcyAobXV0YXRlKCkpLgogICAgLSBDb2xsYXBzZSBtYW55IHZhbHVlcyBkb3duIHRvIGEgc2luZ2xlIHN1bW1hcnkgKHN1bW1hcmlzZSgpKS4KCgojIyMgNS4yIEZpbHRlciByb3dzIHdpdGggZmlsdGVyKCkKCgotIEZpbHRlcigpIGFsbG93cyB5b3UgdG8gc3Vic2V0IG9ic2VydmF0aW9ucyBiYXNlZCBvbiB0aGVpciB2YWx1ZXMKCiAgICAtIGZpcnN0IGFyZ3VtZW50IGlzIHRoZSBuYW1lIG9mIHRoZSBkYXRhIGZyYW1lLiBUaGUgc2Vjb25kIGFuZCBzdWJzZXF1ZW50IGFyZ3VtZW50cyBhcmUgdGhlIGV4cHJlc3Npb25zIHRoYXQgZmlsdGVyIHRoZSBkYXRhIGZyYW1lLgoKLSBUbyBzYXZlIHRoZSByZXN1bHQgbmVlZCB0byB1c2UgdGhlIGFzc2lnbm1lbnQgb3BlcmF0b3IsIDwtOgoKICAgIC0gamFuMSA8LSBmaWx0ZXIoZmxpZ2h0cywgbW9udGggPT0gMSwgZGF5ID09IDEpCiAgICAtIHVzZSA9PSBub3QgPQogICAgLSAgJiBpcyDigJxhbmTigJ0sIHwgaXMg4oCcb3LigJ0sIGFuZCAhIGlzIOKAnG5vdOKAnQogICAgLSBzaG9ydC1oYW5kIG0gaXMgeCAlaW4lIHkuIFNlbGVjdCBldmVyeSByb3cgd2hlcmUgeCBpcyBvbmUgb2YgdGhlIHZhbHVlcyBpbiB5LgoKLSBJZiB5b3Ugd2FudCB0byBkZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBtaXNzaW5nLCB1c2UgaXMubmEoKQotIGZpbHRlcigpIG9ubHkgaW5jbHVkZXMgcm93cyB3aGVyZSB0aGUgY29uZGl0aW9uIGlzIFRSVUU7IGl0IGV4Y2x1ZGVzIGJvdGggRkFMU0UgYW5kIE5BIHZhbHVlcy4KICAgIAoKIyMgNS4yLjQgRXhlcmNpc2VzCgoxLiAKICAgIDFhLiBBbGwgZmxpZ2h0cyB0aGF0IGhhZCBhbiBhcnJpdmFsIGRlbGF5IG9mIHR3byBvciBtb3JlIGhvdXJzCmBgYHtyfQpmaWx0ZXIoZmxpZ2h0cywgYXJyX2RlbGF5ID49IDEyMCkKYGBgCgogCiAgMWIuIEFsbCBmbGlnaHRzIHRoYXQgaGFkIGZsZXcgdG8gSG91c3RvbiAoSUFIIG9yIEhPVSkKYGBge3J9CmZpbHRlcihmbGlnaHRzLCBkZXN0ID09ICJJQUgiIHwgZGVzdCA9PSAiSE9VIikKYGBgCgoKICAxYy4gQWxsIGZsaWdodHMgdGhhdCBoYWQgd2VyZSBvcGVyYXRlZCBieSBVbml0ZWQsIEFtZXJpY2FuLCBvciBEZWx0YQpgYGB7cn0KZmlsdGVyKGZsaWdodHMsIGNhcnJpZXIgJWluJSBjKCJBQSIsICJETCIsICJVQSIpKQpgYGAKCiAgMWQuIEFsbCBmbGlnaHRzIHRoYXQgaGFkIGRlcGFydGVkIGluIHN1bW1lciAoSnVseSwgQXVndXN0LCBhbmQgU2VwdGVtYmVyCmBgYHtyfQpmaWx0ZXIoZmxpZ2h0cywgbW9udGggPT0gNyB8IG1vbnRoID09IDggfCBtb250aCA9PSA5KQpgYGAKCiAgMWUuIEFsbCBmbGlnaHRzIHRoYXQgaGFkIGFycml2ZWQgbW9yZSB0aGFuIHR3byBob3VycyBsYXRlLCBidXQgZGlkbuKAmXQgbGVhdmUgbGF0ZQpgYGB7cn0KZmlsdGVyKGZsaWdodHMsIGFycl9kZWxheSA+IDEyMCwgZGVwX2RlbGF5IDw9IDApCmBgYAoKICAxZi4gQWxsIGZsaWdodHMgdGhhdCB3ZXJlIGRlbGF5ZWQgYnkgYXQgbGVhc3QgYW4gaG91ciwgYnV0IG1hZGUgdXAgb3ZlciAzMCBtaW51dGVzIGluIGZsaWdodApgYGB7cn0KZmlsdGVyKGZsaWdodHMsIGRlcF9kZWxheSA+PSA2MCwgZGVwX2RlbGF5IC0gYXJyX2RlbGF5ID4gMzApCmBgYAoKCiAgMWcuIEFsbCBmbGlnaHRzIHRoYXQgd2VyZSBkcGFydGVkIGJldHdlZW4gbWlkbmlnaHQgYW5kIDZhbSAoaW5jbHVzaXZlKQpgYGB7cn0KZmlsdGVyKGZsaWdodHMsIGRlcF90aW1lICUlIDI0MDAgPD0gNjAwKQpgYGAKCjIuIEFub3RoZXIgdXNlZnVsIGRwbHlyIGZpbHRlcmluZyBoZWxwZXIgaXMgYmV0d2VlbigpLiBXaGF0IGRvZXMgaXQgZG8/IENhbiB5b3UgdXNlIGl0IHRvIHNpbXBsaWZ5IHRoZSBjb2RlIG5lZWRlZCB0byBhbnN3ZXIgdGhlIHByZXZpb3VzIGNoYWxsZW5nZXM/CgoKVGhlIGV4cHJlc3Npb24gYmV0d2Vlbih4LCBsZWZ0LCByaWdodCkgaXMgZXF1aXZhbGVudCB0byB4ID49IGxlZnQgJiB4IDw9IHJpZ2h0LiBJIGNvdWxkIGhhZCB1c2UgaXQgdG8gc2ltcGxpZnkgdGhlIGNvZGUgbmVlZGVkIHRvIGFuc3dlciB0aGUgcHJldmlvdXMgY2hhbGxlbmdlcwoKCgozLiBIb3cgbWFueSBmbGlnaHRzIGhhdmUgYSBtaXNzaW5nIGRlcF90aW1lPyBXaGF0IG90aGVyIHZhcmlhYmxlcyBhcmUgbWlzc2luZz8gV2hhdCBtaWdodCB0aGVzZSByb3dzIHJlcHJlc2VudD8KCmBgYHtyfQpmaWx0ZXIoZmxpZ2h0cywgaXMubmEoZGVwX3RpbWUpKQpgYGAKCgoxMDAwIGZsaWdodHMgaGF2ZSBhIG1pc3NpbmcgZGVwX3RpbWUuIFRoZSBhcnJpdmFsIHRpbWUgKGFycl90aW1lKSBpcyBhbHNvIG1pc3NpbmcuCgoKCjQuIFdoeSBpcyBOQSBeIDAgbm90IG1pc3Npbmc/IFdoeSBpcyBOQSB8IFRSVUUgbm90IG1pc3Npbmc/IFdoeSBpcyBGQUxTRSAmIE5BIG5vdCBtaXNzaW5nPyBDYW4geW91IGZpZ3VyZSBvdXQgdGhlIGdlbmVyYWwgcnVsZT8gKE5BICogMCBpcyBhIHRyaWNreSBjb3VudGVyZXhhbXBsZSEpCgoKTkEgXiAwIGlzIG5vdCBtaXNzaW5nIGJlY2F1c2UgZm9yIGFsbCBudW1lcmljIHZhbHVlcyB4IF4gMCA9IDEKTkEgfCBUUlVFIG5vdCBtaXNzaW5nIGJlY2F1c2UgeCBvciBUUlVFIGlzIFRSVUUgZm9yIGFsbCB2YWx1ZXMgb2YgeApGQUxTRSAmIE5BIG5vdCBtaXNzaW5nIGJlY2F1ZXMgYW55dGhpbmcgYW5kIEZBTFNFIGlzIGFsd2F5cyBGQUxTRQpOQSB0aW1lcyAwIGlzIG5vdCBlcXVhbCB0byAwIGlzIHRoYXQgw5cgdGltZXMg4oieIGFuZCB4IHRpbWVzIOKIkuKIniBpcyB1bmRlZmluZWQuIFIgcmVwcmVzZW50cyB1bmRlZmluZWQgcmVzdWx0cyBhcyBOYU4gKG5vdCBhIG51bWJlcikuCgoKCiMjIyA1LjMgQXJyYW5nZSByb3dzIHdpdGggYXJyYW5nZSgpCgotIGFycmFuZ2UoKSB3b3JrcyBzaW1pbGFybHkgdG8gZmlsdGVyKCkKICAgIC0gZXhjZXB0IHRoYXQgaW5zdGVhZCBvZiBzZWxlY3Rpbmcgcm93cyBpdCBjaGFuZ2VzIHRoZWlyIG9yZGVyCiAgICAtIEl0IHRha2VzIGEgZGF0YSBmcmFtZSBhbmQgYSBzZXQgb2YgY29sdW1uIG5hbWVzIChvciBtb3JlIGNvbXBsaWNhdGVkIGV4cHJlc3Npb25zKSB0byBvcmRlciBieS4KICAgIAotIFVzZSBkZXNjKCkgdG8gcmUtb3JkZXIgYnkgYSBjb2x1bW4gaW4gZGVzY2VuZGluZyBvcmRlcjoKICAgIC0gYXJyYW5nZShmbGlnaHRzLCBkZXNjKGRlcF9kZWxheSkpCiAgICAKLSBNaXNzaW5nIHZhbHVlcyBhcmUgYWx3YXlzIHNvcnRlZCBhdCB0aGUgZW5kLgoKIyMgNS4zLjEgRXhlcmNpc2VzIAoKMS4gSG93IGNvdWxkIHlvdSB1c2UgYXJyYW5nZSgpIHRvIHNvcnQgYWxsIG1pc3NpbmcgdmFsdWVzIHRvIHRoZSBzdGFydD8gKEhpbnQ6IHVzZSBpcy5uYSgpKS4KICAKYGBge3J9CmFycmFuZ2UoZmxpZ2h0cywgZGVzYyhpcy5uYShkZXBfdGltZSkpLCBkZXBfdGltZSkKYGBgCgoKMi4gU29ydCBmbGlnaHRzIHRvIGZpbmQgdGhlIG1vc3QgZGVsYXllZCBmbGlnaHRzLiBGaW5kIHRoZSBmbGlnaHRzIHRoYXQgbGVmdCBlYXJsaWVzdC4KCmBgYHtyfQphcnJhbmdlKGZsaWdodHMsIGRlcF9kZWxheSkKYGBgCgpGbGlnaHQgQjYgOTcgKEpGSyB0byBERU4pIGRlcGFydCBvbiBEZWNlbWJlciAwNywgMjAxMyBhdCAyMToyMyBkZXBhcnRlZCA0MyBtaW51dGVzIGVhcmx5LgoKCjMuIFNvcnQgZmxpZ2h0cyB0byBmaW5kIHRoZSBmYXN0ZXN0IChoaWdoZXN0IHNwZWVkKSBmbGlnaHRzLgoKYGBge3J9CmZhc3Rlc3RfZmxpZ2h0cyA8LSBtdXRhdGUoZmxpZ2h0cywgbXBoID0gZGlzdGFuY2UgLyBhaXJfdGltZSAqIDYwKQpmYXN0ZXN0X2ZsaWdodHMgPC0gc2VsZWN0KAogIGZhc3Rlc3RfZmxpZ2h0cywgbXBoLCBkaXN0YW5jZSwgYWlyX3RpbWUsCiAgZmxpZ2h0LCBvcmlnaW4sIGRlc3QsIHllYXIsIG1vbnRoLCBkYXkKKQpgYGAKCgoKNC4gV2hpY2ggZmxpZ2h0cyB0cmF2ZWxsZWQgdGhlIGZhcnRoZXN0PyBXaGljaCB0cmF2ZWxsZWQgdGhlIHNob3J0ZXN0PwoKCmBgYHtyfQphcnJhbmdlKGZsaWdodHMsIGRlc2MoZGlzdGFuY2UpKQoKYGBgCgoKVGhlIGxvbmdlc3QgZmxpZ2h0IGlzIEhBIDUxLCBKRksgdG8gSE5MLCB3aGljaCBpcyA0LDk4MyBtaWxlcy4KCgpgYGB7cn0KYXJyYW5nZShmbGlnaHRzLCBkaXN0YW5jZSkKYGBgCgpUaGUgc2hvcnRlc3QgZmxpZ2h0IGlzIFVTIDE2MzIsIEVXUiB0byBMR0EsIHdoaWNoIGlzIG9ubHkgMTcgbWlsZXMuCgoKCiMjIyA1LjQgU2VsZWN0IGNvbHVtbnMgd2l0aCBzZWxlY3QoKQoKCi0gc2VsZWN0KCkgYWxsb3dzIHlvdSB0byByYXBpZGx5IHpvb20gaW4gb24gYSB1c2VmdWwgc3Vic2V0IHVzaW5nIG9wZXJhdGlvbnMgYmFzZWQgb24gdGhlIG5hbWVzIG9mIHRoZSB2YXJpYWJsZXMuCgotIHN0YXJ0c193aXRoKCJhYmMiKTogbWF0Y2hlcyBuYW1lcyB0aGF0IGJlZ2luIHdpdGgg4oCcYWJj4oCdLgoKLSBlbmRzX3dpdGgoInh5eiIpOiBtYXRjaGVzIG5hbWVzIHRoYXQgZW5kIHdpdGgg4oCceHl64oCdLgoKLSBjb250YWlucygiaWprIik6IG1hdGNoZXMgbmFtZXMgdGhhdCBjb250YWluIOKAnGlqa+KAnS4KCi0gbWF0Y2hlcygiKC4pXFwxIik6IHNlbGVjdHMgdmFyaWFibGVzIHRoYXQgbWF0Y2ggYSByZWd1bGFyIGV4cHJlc3Npb24uIFRoaXMgb25lIG1hdGNoZXMgYW55IHZhcmlhYmxlcyB0aGF0IGNvbnRhaW4gcmVwZWF0ZWQgY2hhcmFjdGVycy4gWW914oCZbGwgbGVhcm4gbW9yZSBhYm91dCByZWd1bGFyIGV4cHJlc3Npb25zIGluIHN0cmluZ3MuCgotIG51bV9yYW5nZSgieCIsIDE6Myk6IG1hdGNoZXMgeDEsIHgyIGFuZCB4My4KCi0gP3NlbGVjdCBmb3IgbW9yZSBkZXRhaWxzCgotIHVzZSByZW5hbWUoKSwgd2hpY2ggaXMgYSB2YXJpYW50IG9mIHNlbGVjdCgpIHRoYXQga2VlcHMgYWxsIHRoZSB2YXJpYWJsZXMgdGhhdCBhcmVu4oCZdCBleHBsaWNpdGx5IG1lbnRpb25lZDoKCiAgICAtIHJlbmFtZShmbGlnaHRzLCB0YWlsX251bSA9IHRhaWxudW0pCiAgICAKCgojIyA1LjQuMSBFeGVyY2lzZXMKCgoxLiBCcmFpbnN0b3JtIGFzIG1hbnkgd2F5cyBhcyBwb3NzaWJsZSB0byBzZWxlY3QgZGVwX3RpbWUsIGRlcF9kZWxheSwgYXJyX3RpbWUsIGFuZCBhcnJfZGVsYXkgZnJvbSBmbGlnaHRzLgoKYGBge3J9CnNlbGVjdChmbGlnaHRzLCBkZXBfdGltZSwgZGVwX2RlbGF5LCBhcnJfdGltZSwgYXJyX2RlbGF5KQpzZWxlY3QoZmxpZ2h0cywgNCwgNiwgNywgOSkKYGBgCgoKCjIuIFdoYXQgaGFwcGVucyBpZiB5b3UgaW5jbHVkZSB0aGUgbmFtZSBvZiBhIHZhcmlhYmxlIG11bHRpcGxlIHRpbWVzIGluIGEgc2VsZWN0KCkgY2FsbD8KCgpUaGUgc2VsZWN0KCkgY2FsbCBpZ25vcmVzIHRoZSBkdXBsaWNhdGlvbi4KCgoKMy4gV2hhdCBkb2VzIHRoZSBvbmVfb2YoKSBmdW5jdGlvbiBkbz8gV2h5IG1pZ2h0IGl0IGJlIGhlbHBmdWwgaW4gY29uanVuY3Rpb24gd2l0aCB0aGlzIHZlY3Rvcj8KCmBgYHtyfQp2YXJzIDwtIGMoInllYXIiLCAibW9udGgiLCAiZGF5IiwgImRlcF9kZWxheSIsICJhcnJfZGVsYXkiKQpgYGAKCgpUaGUgb25lX29mKCkgZnVuY3Rpb24gc2VsZWN0cyB2YXJpYWJsZXMgd2l0aCBhIGNoYXJhY3RlciB2ZWN0b3IgcmF0aGVyIHRoYW4gdW5xdW90ZWQgdmFyaWFibGUgbmFtZSBhcmd1bWVudHMuIFRoaXMgaXMgaGVscGZ1bCBiZWNhdXNlIGl0IGlzIGVhc2llciB0byBtYWtlIGEgY2hhcmFjdGVyIHZlY3RvcnMgd2l0aCB2YXJpYWJsZSBuYW1lcyB0aGFuIHRvIGNyZWF0ZSB1bnF1b3RlZCB2YXJpYWJsZSBuYW1lcy4KCgoKNC4gRG9lcyB0aGUgcmVzdWx0IG9mIHJ1bm5pbmcgdGhlIGZvbGxvd2luZyBjb2RlIHN1cnByaXNlIHlvdT8gSG93IGRvIHRoZSBzZWxlY3QgaGVscGVycyBkZWFsIHdpdGggY2FzZSBieSBkZWZhdWx0PyBIb3cgY2FuIHlvdSBjaGFuZ2UgdGhhdCBkZWZhdWx0PwoKYGBge3J9CnNlbGVjdChmbGlnaHRzLCBjb250YWlucygiVElNRSIpKQpgYGAKCgpUaGUgZGVmYXVsdCBiZWhhdmlvciBmb3IgY29udGFpbnMoKSBpcyB0byBpZ25vcmUgY2FzZS4gQ2FuIGNoYW5nZSB0aGUgYmVoYXZpb3IgYnkgYWRkaW5nIHRoZSBhcmd1bWVudCBpZ25vcmUuY2FzZSA9IEZBTFNFLgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo=